﻿using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WCAD.Kean
{
    public class LeaderCmds
    {
        //https://www.keanw.com/2016/09/jigging-an-autocad-leader-with-directional-text-using-net.html
        class DirectionalLeaderJig : EntityJig

        {

            private Point3d _start, _end;

            private string _contents;

            private int _index;

            private int _lineIndex;

            private bool _started;



            public DirectionalLeaderJig(string txt, Point3d start, MLeader ld) : base(ld)

            {

                // Store info that's passed in, but don't init the MLeader



                _contents = txt;

                _start = start;

                _end = start;



                _started = false;

            }



            // A fairly standard Sampler function



            protected override SamplerStatus Sampler(JigPrompts prompts)

            {

                var po = new JigPromptPointOptions();

                po.UserInputControls =

                  (UserInputControls.Accept3dCoordinates |

                   UserInputControls.NoNegativeResponseAccepted);

                po.Message = "\nEnd point";



                var res = prompts.AcquirePoint(po);



                if (_end == res.Value)

                {

                    return SamplerStatus.NoChange;

                }

                else if (res.Status == PromptStatus.OK)

                {

                    _end = res.Value;

                    return SamplerStatus.OK;

                }

                return SamplerStatus.Cancel;

            }



            protected override bool Update()

            {

                var ml = (MLeader)Entity;



                if (!_started)

                {

                    if (_start.DistanceTo(_end) > Tolerance.Global.EqualPoint)

                    {

                        // When the jig actually starts - and we have mouse movement -

                        // we create the MText and init the MLeader



                        ml.ContentType = ContentType.MTextContent;

                        var mt = new MText();

                        mt.Contents = _contents;

                        ml.MText = mt;



                        // Create the MLeader cluster and add a line to it



                        _index = ml.AddLeader();

                        _lineIndex = ml.AddLeaderLine(_index);



                        // Set the vertices on the line



                        ml.AddFirstVertex(_lineIndex, _start);

                        ml.AddLastVertex(_lineIndex, _end);



                        // Make sure we don't do this again



                        _started = true;

                    }

                }

                else

                {

                    // We only make the MLeader visible on the second time through

                    // (this also helps avoid some strange geometry flicker)



                    ml.Visible = true;



                    // We already have a line, so just set its last vertex



                    ml.SetLastVertex(_lineIndex, _end);

                }



                if (_started)

                {

                    // Set the direction of the text to depend on the X of the end-point

                    // (i.e. is if to the left or right of the start-point?)



                    var dl = new Vector3d((_end.X >= _start.X ? 1 : -1), 0, 0);

                    ml.SetDogleg(_index, dl);

                }



                return true;

            }

        }



        [CommandMethod("DL")]

        public void DirectionalLeader()

        {

            var doc = Application.DocumentManager.MdiActiveDocument;

            var ed = doc.Editor;

            var db = doc.Database;



            // Ask the user for the string and the start point of the leader



            var pso = new PromptStringOptions("\nEnter text");

            pso.AllowSpaces = true;

            var pr = ed.GetString(pso);



            if (pr.Status != PromptStatus.OK)

                return;



            var ppr = ed.GetPoint("\nStart point of leader");

            if (ppr.Status != PromptStatus.OK)

                return;



            // Start a transaction, as we'll be jigging a db-resident object



            using (var tr = db.TransactionManager.StartTransaction())

            {

                var bt =

                  (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead, false);

                var btr =

                  (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite, false);



                // Create and pass in an invisible MLeader

                // This helps avoid flickering when we start the jig



                var ml = new MLeader();

                ml.Visible = false;



                // Create jig



                var jig = new DirectionalLeaderJig(pr.StringResult, ppr.Value, ml);



                // Add the MLeader to the drawing: this allows it to be displayed



                btr.AppendEntity(ml);

                tr.AddNewlyCreatedDBObject(ml, true);



                // Set end point in the jig



                var res = ed.Drag(jig);



                // If all is well, commit



                if (res.Status == PromptStatus.OK)

                {

                    tr.Commit();

                }

            }

        }

    }
}
